package com.sds.sweng.swat.miplatform.service.viewers;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Table;

import com.sds.sweng.swat.miplatform.service.figures.components.ValidationComponent;
import com.sds.sweng.swat.miplatform.service.layouts.ValidationViewerLayout;
import com.sds.sweng.swat.miplatform.service.pages.ServiceControlArea;
import com.sds.sweng.swat.miplatform.service.validation.ValidationInfo;
import com.sds.sweng.swat.miplatform.service.validation.ValidationProperties;
import com.sds.sweng.swat.miplatform.service.validation.ValidationProperty;
import com.sds.sweng.swat.miplatform.service.validation.ValidationType;

public class ValidationViewer extends Composite {

	TableViewer validationTable;
	StyledText validationText;

	String serviceId;

	ServiceControlArea area;

	private int locale;

	public ValidationViewer(Composite parent, int locale) {
		super(parent, SWT.NONE);

		this.locale = locale;

		init();
	}

	public void setArea(ServiceControlArea area) {
		this.area = area;
	}

	private void init() {
		setLayout(new ValidationViewerLayout());

		validationTable = new TableViewer(this, SWT.SINGLE | SWT.V_SCROLL | SWT.FULL_SELECTION);
		TableViewerColumn keyColumn = new TableViewerColumn(validationTable, SWT.NONE);
		keyColumn.getColumn().setText("Column");
		keyColumn.getColumn().setWidth(100);
		keyColumn.getColumn().setResizable(true);

		TableViewerColumn valueColumn = new TableViewerColumn(validationTable, SWT.NONE);
		valueColumn.getColumn().setText("Value");
		valueColumn.getColumn().setWidth(170);
		valueColumn.getColumn().setResizable(true);

		Table table = validationTable.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		validationTable.setContentProvider(new IStructuredContentProvider() {

			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
				refresh();
			}

			public void dispose() {
				// do nothing
			}

			public Object[] getElements(Object inputElement) {
				ValidationComponent validationComponent = (ValidationComponent) inputElement;
				ValidationInfo validationInfo = validationComponent.getValidationInfo(serviceId);

				return validationComponent.getValidationProperties(validationInfo);
			}
		});

		validationTable.setLabelProvider(new ValidationLabelProvider(locale));

		CellEditor[] cellEditors = new CellEditor[2];
		cellEditors[0] = new TextCellEditor(table, SWT.READ_ONLY);
		cellEditors[1] = new TextCellEditor(table);

		validationTable.setColumnProperties(new String[] {"key", "value"});
		validationTable.setCellEditors(cellEditors);
		validationTable.setCellModifier(new ValidationCellModifier(this, locale));

		validationText = new StyledText(this, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
		validationText.setSize(SWT.DEFAULT, 60);
		validationText.addKeyListener(new KeyAdapter() {

			public void keyReleased(KeyEvent e) {
				if (e.keyCode == 13) {
					ValidationComponent validationComponent = (ValidationComponent) validationTable.getInput();
					validationComponent.getValidationInfo(serviceId).setInfoFromString(validationText.getText());
					refresh();

					area.setServiceValidationString();
				}
			}
		});
	}

	public void setInput(ValidationComponent selectedComponent, String serviceId) {
		this.serviceId = serviceId;

		validationTable.setInput(selectedComponent);
		validationText.setText(selectedComponent.getValidationInfo(serviceId).toString());
	}

	public void refresh() {
		validationTable.refresh(false);

		ValidationComponent validationComponent = (ValidationComponent) validationTable.getInput();

		if (validationComponent == null) {
			return;
		}

		String validationString = validationComponent.getValidationInfo(serviceId).toString();
		validationText.setText(validationString);
		validationComponent.refresh(serviceId);
	}

}

class ValidationCellModifier implements ICellModifier {

	private ValidationViewer validationViewer;
	private int locale;

	public ValidationCellModifier(ValidationViewer validationViewer, int locale) {
		this.validationViewer = validationViewer;
		this.locale = locale;
	}

	public boolean canModify(Object element, String property) {
		if ("key".equals(property))
			return false;
		else {
			ValidationProperty validationProperty = (ValidationProperty) element;

			TableViewer validationTable = validationViewer.validationTable;
			Table table = validationTable.getTable();
			CellEditor[] cellEditors = validationTable.getCellEditors();

			ValidationComponent validationComponent = (ValidationComponent) validationTable.getInput();

			if (ValidationProperties.COMPONENT_NAME[locale].equals(validationProperty.getKey(locale))) {
				cellEditors[1] = new TextCellEditor(table);
				validationTable.setCellEditors(cellEditors);
				return false;
			} else if (ValidationProperties.ID[locale].equals(validationProperty.getKey(locale))) {
				cellEditors[1] = new TextCellEditor(table);
				validationTable.setCellEditors(cellEditors);
				return false;
			} else {
				if (ValidationProperties.TYPE[locale].equals(validationProperty.getKey(locale))) {
					cellEditors[1] = new ComboBoxCellEditor(table, validationComponent.getValidationTypes(), SWT.READ_ONLY);
				} else if (ValidationProperties.REQUIRED[locale].equals(validationProperty.getKey(locale))) {
					cellEditors[1] = new CheckboxCellEditor(table);
				} else if (ValidationProperties.COMPARE_OP[locale].equals(validationProperty.getKey(locale))) {
					cellEditors[1] = new ComboBoxCellEditor(table, validationComponent.getValidationCompareOperators(), SWT.READ_ONLY);
				} else {
					cellEditors[1] = new TextCellEditor(table);
				}

				validationTable.setCellEditors(cellEditors);

				return true;
			}
		}
	}

	public Object getValue(Object element, String property) {
		ValidationProperty validationProperty = (ValidationProperty) element;

		ValidationComponent validationComponent = (ValidationComponent) validationViewer.validationTable.getInput();

		if ("key".equals(property))
			return validationProperty.getKey(locale);
		else {
			if (ValidationProperties.TYPE[locale].equals(validationProperty.getKey(locale))) {
				if (StringUtils.isEmpty(validationProperty.getStringValue())) {
					return 0;
				} else if (StringUtils.isNumeric(validationProperty.getStringValue())) {
					return Integer.parseInt(validationProperty.getStringValue());
				} else {
					return ArrayUtils.indexOf(validationComponent.getValidationTypes(), validationProperty.getStringValue());
				}
			} else if (ValidationProperties.REQUIRED[locale].equals(validationProperty.getKey(locale))) {
				return Boolean.valueOf(validationProperty.getStringValue());
			} else if (ValidationProperties.COMPARE_OP[locale].equals(validationProperty.getKey(locale))) {
				if (StringUtils.isEmpty(validationProperty.getStringValue())) {
					return 0;
				} else if (StringUtils.isNumeric(validationProperty.getStringValue())) {
					return Integer.parseInt(validationProperty.getStringValue());
				} else {
					return ArrayUtils.indexOf(validationComponent.getValidationCompareOperators(), validationProperty.getStringValue());
				}
			} else {
				return validationProperty.getStringValue();
			}
		}
	}

	public void modify(Object element, String property, Object value) {
		if ("key".equals(property))
			return;

		if (element instanceof Item)
			element = ((Item) element).getData();

		ValidationProperty validationProperty = (ValidationProperty) element;

		ValidationComponent validationComponent = (ValidationComponent) validationViewer.validationTable.getInput();
		ValidationInfo validationInfo = validationComponent.getValidationInfo(validationViewer.serviceId);

		if (ValidationProperties.BUSINESS_NAME[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.businessName = String.valueOf(value);
		} else if (ValidationProperties.REQUIRED_GROUP[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.requiredGroup = String.valueOf(value);
		} else if (ValidationProperties.TYPE[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.type = String.valueOf(value);
			changeComboText();
		} else if (ValidationProperties.REQUIRED[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.required = Boolean.valueOf(String.valueOf(value));
			if (validationInfo.required && !ValidationType.isValidType(validationInfo.type)) {
				validationInfo.type = ValidationType.CUSTOM;
				validationInfo.partied = true;
			}
		} else if (ValidationProperties.MIN_LENGTH[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.minLength = ValidationInfo.toPositiveInteger(value);
		} else if (ValidationProperties.MAX_LENGTH[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.maxLength = ValidationInfo.toPositiveInteger(value);
		} else if (ValidationProperties.MIN[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.min = ValidationInfo.toNumber(value);
		} else if (ValidationProperties.MAX[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.max = ValidationInfo.toNumber(value);
		} else if (ValidationProperties.COMPARE_OP[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.compOp = String.valueOf(value);
			changeComboText();
		} else if (ValidationProperties.COMPARE_TARGET[locale].equals(validationProperty.getKey(locale))) {
			validationInfo.compTarget = String.valueOf(value);
		}

		validationViewer.refresh();
		validationViewer.area.setServiceValidationString();
	}

	private void changeComboText() {
		ValidationComponent validationComponent = (ValidationComponent) validationViewer.validationTable.getInput();
		ValidationInfo validationInfo = validationComponent.getValidationInfo(validationViewer.serviceId);

		if (!StringUtils.isEmpty(validationInfo.type) && StringUtils.isNumeric(validationInfo.type)) {
			validationInfo.type = validationComponent.getValidationTypes()[Integer.parseInt(validationInfo.type)];

			if (ValidationType.NONE.equals(validationInfo.type)) {
				validationInfo.partied = false;
			} else {
				validationInfo.partied = true;
			}
		}

		if (!StringUtils.isEmpty(validationInfo.compOp) && StringUtils.isNumeric(validationInfo.compOp)) {
			validationInfo.compOp = validationComponent.getValidationCompareOperators()[Integer.parseInt(validationInfo.compOp)];
		}
	}

}

class ValidationLabelProvider extends LabelProvider implements ITableLabelProvider {

	private int locale;

	public ValidationLabelProvider(int locale) {
		this.locale = locale;
	}

	public Image getColumnImage(Object element, int columnIndex) {
		return null;
	}

	public String getColumnText(Object element, int columnIndex) {
		ValidationProperty validationProperty = (ValidationProperty) element;

		switch (columnIndex) {
			case 0:
				return validationProperty.getKey(locale);
			case 1:
				return validationProperty.getStringValue();
			default:
				return null;
		}
	}

}
